#include "main.h"
#include "stm32f4xx_hal.h"
#include "cmsis_os.h"
#include "lwip.h"
#include "sysdef.h"
#include "sockets.h"
#include "flash_if.h"
#include "mb.h"

#define JNZS_DEBUG printf
#define JNZS_INFO printf

extern osThreadId ETHCMDTaskHandle;
extern osThreadId RWSensorIOTaskHandle;
extern osThreadId GUIMainTaskHandle;
extern osThreadId TouchTaskHandle;
extern osThreadId UARTCMDTaskHandle;
static int LWIP_init_OK = 0;

typedef struct sensor_data
{
	float WaterPressBef;	
	float WaterPressAft;	
	float OilPress;	
	float OilTemp;	
	float OilPos;	
	float OilVel;	
	int InStat;
	int OutStat;	
	int DACVal1;	
	int DACVal2;	
}SENSORDATA;
typedef struct Ctrlinfo
{
	int PN;	
  int SN;	
  int ManuData;	
  int HWVer;
  int SWVer;	
	float adcscale[8];
	float adcoffset[8];
}CTRLINFO;

typedef struct cmdheader
{
	char mode;
	char bytenum;
	short cmd;
}CMDHEADER;

extern char guartbuf[MAXCOMLEN];
char gethbuf[MAXCOMLEN];


SENSORDATA gsensor={0};
CTRLINFO gctrlinfo={0};
RcvS gRev;


void appdatainit()
{
	int i;
	gctrlinfo.SWVer=0x201705;
	for(i=0;i<8;i++)
	{
		gctrlinfo.adcscale[i] = 1;
		gctrlinfo.adcoffset[i] = 0;
	}
	
  gRev.sr1 = 0;
	gRev.sr2 = 0;
	gRev.cnt = 0;
	
	gsensor.InStat = 0xff;
	gsensor.WaterPressAft = 1.3;
}
extern osSemaphoreId gDataSemHandle;

void sem_memcpy(void *dst, void *src, int cnt)
{
	osSemaphoreWait(gDataSemHandle, osWaitForever);
	memcpy(dst, src, cnt);
	osSemaphoreRelease(gDataSemHandle);
}

/*return:
 1: process ok
 0: com buf error
*/
int processCom(char *rec, char *send, int* sendcnt)
{
	int ret=1;
	CMDHEADER *pheader;
	CMDHEADER *pheader_s;
	pheader = (CMDHEADER *)rec;
  pheader_s = (CMDHEADER *)send;
	
	pheader_s->mode = pheader->mode;
	pheader_s->cmd = pheader->cmd;
	if(pheader->mode == 'G')
	{		
		if(pheader->cmd<10)
		{
			pheader_s->bytenum = 1;
			sem_memcpy(send+4, (void *)(((int *)&gsensor)+pheader->cmd), 4);
		
		}
		else if(pheader->cmd == 100)
		{
			pheader_s->bytenum = 10;
			sem_memcpy(send+4, (void *)&gsensor, 4*10);
		}
  }
	else if(pheader->mode == 'S')
	{
		if((pheader->cmd == 8) || (pheader->cmd == 9) || (pheader->cmd == 7))
		{
			pheader_s->bytenum = 1;
			sem_memcpy((void *)(((int *)&gsensor)+pheader->cmd), rec+4, 4);
		}
		else if((pheader->cmd == 200) && (pheader->bytenum == 3 ))
		{
			pheader_s->bytenum = 3;
			sem_memcpy((void *)(((int *)&gsensor)+7), rec+4, 4*3);
		}
		else if(pheader->cmd == 300)
		{
			unsigned int flashaddr = USER_FLASH_FIRST_PAGE_ADDRESS;
			FLASH_If_Init();
			FLASH_If_Erase(USER_FLASH_FIRST_PAGE_ADDRESS);
			FLASH_If_Write(&flashaddr, (unsigned int *)&gctrlinfo, sizeof(gctrlinfo)/4);
		}
	}
	else
	{
		ret = 0;
	}
	send[4+4*pheader_s->bytenum] = 0x0D;
	send[4+4*pheader_s->bytenum + 1] = 0x0A;
	*sendcnt = 6 + 4 * pheader_s->bytenum;
	return ret;
}

/* USER CODE END 4 */
extern float adc1val;
extern short Temperate;
/* StartETHCMDTask function */
void StartETHCMDTask(void const * argument)
{
  /* init code for LWIP */
  MX_LWIP_Init();
	LAN8720_Get_Speed();
	
	LWIP_init_OK = 1;
	unsigned int adcx;
	float temp;
	struct sockaddr_in my_addr; 
	unsigned short port = 8086;
	int sockfd;
	
	sockfd = socket(AF_INET, SOCK_STREAM, 0);   
  if(sockfd < 0)  
  {  
			printf("create socket error\n");
  }  
	
 
  //bzero(&my_addr, sizeof(my_addr));      
  my_addr.sin_family = AF_INET;   
  my_addr.sin_port   = htons(port);  
  my_addr.sin_addr.s_addr = htonl(INADDR_ANY);   
      
  
  int err_log = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr));  
  if( err_log != 0)  
  {  
        printf("binding");  
        closesocket(sockfd);         
  } 
	
	err_log = listen(sockfd, 1); 
  if(err_log != 0)  
  {  
        printf("listen error\n");  
        closesocket(sockfd);          
  }
 
  struct sockaddr_in client_addr;          
  char cli_ip[INET_ADDRSTRLEN] = "";       
  socklen_t cliaddr_len = sizeof(client_addr);         
  int connfd; 
  int flag = 1;
  int result; 	
	int rcvcnt;
	int sendcnt,sendout;
	char replybuf[MAXCOMLEN];
	CMDHEADER *pheader;
	pheader = (CMDHEADER *)gethbuf;
  /* Infinite loop */
  for(;;)
  {
     connfd = accept(sockfd, (struct sockaddr*)&client_addr, &cliaddr_len);         
     if(connfd < 0)  
     {  
         JNZS_DEBUG("accept error!!!");  
         continue;  
     }  
     result = setsockopt(connfd,            /* socket affected */
                                 IPPROTO_TCP,     /* set option at TCP level */
                                 TCP_NODELAY,     /* name of option */
                                 (char *) &flag,  /* the cast is historical
                                                         cruft */
                                 sizeof(int));    /* length of option value */

     if (result < 0)
     {
            JNZS_INFO("TCP_NODELAY  SET Error: %d\n", result);
     }
         
     inet_ntop(AF_INET, &client_addr.sin_addr, cli_ip, INET_ADDRSTRLEN);  
     JNZS_DEBUG("client ip=%s,port=%d\n", cli_ip,ntohs(client_addr.sin_port));  
          


     while( (rcvcnt = recv(connfd, gethbuf, sizeof(CMDHEADER), 0)) > 0 ) //first read header
     {   
     
        if(rcvcnt == sizeof(CMDHEADER))
        {       
						rcvcnt = recv(connfd, gethbuf+sizeof(CMDHEADER), pheader->bytenum*4 + 2, 0);
						if((rcvcnt == pheader->bytenum*4 + 2) && (gethbuf[sizeof(CMDHEADER) + rcvcnt - 2] == 0x0D)) 
						{
									if(processCom( gethbuf, replybuf, &sendcnt) == 1)
									{
												 sendout = send(connfd, replybuf, sendcnt, 0);
												 JNZS_INFO("ETH: send buf len %d\n", sendout);
									}
									if( sendcnt < 0)
									 {
												JNZS_DEBUG("send err!\n");
												break;
									 }
						}
						else
						{
									 JNZS_DEBUG("recv char err!\n");
									 recv(connfd, gethbuf, MAXCOMLEN, 0);
						}
         }
         else
         {
              JNZS_DEBUG("recv not enough !\n");
              break;
         }
     }           
     closesocket(connfd);   
     JNZS_DEBUG("client closed!\n");  
		//osDelay(1000);
  }
  /* USER CODE END 5 */ 
}

extern UART_HandleTypeDef huart1;
extern osSemaphoreId guartSemHandle;
void UARTCMDTask(void const * argument)
{
	char replybuf[MAXCOMLEN];
	int sendcnt;
	memset(replybuf, 0, MAXCOMLEN);
	printf("UARTCMDTask task begin CMDHEADER=%d\n",sizeof(CMDHEADER));
	

	for(;;)
	{
		osSemaphoreWait(guartSemHandle, osWaitForever);
		if(processCom(guartbuf,replybuf, &sendcnt) == 1)
		{
			//HAL_UART_Transmit(&huart1, gRev.buf, gRev.cnt,1000);
			HAL_UART_Transmit_DMA(&huart1, (unsigned char*)replybuf, sendcnt);
		}
		else
		{
			printf("UARTCMDTask exec error\n");
		}
	}
}
/*4 to 1*/
void setADCMux(int code)
{
	GPIO_PinState temp = (GPIO_PinState)(code&0x1);
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,temp); 
	temp = (GPIO_PinState)((code>>1)&0x1);
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,temp);
}

int getDI()
{
	int ret=0;
	
	return ret;
}


void setDO(int dout)
{
	
	
	return;
}

void DACout(int dac1, int dac2)
{
	return;
}
/* USER CODE BEGIN 4 */
void RWSensorIOTask(void const * argument)
{
	printf("RWSensorIO task begin\n");
	int i;
	float fADCval[8];
	int adctemp;
	int IOin;
	int IOout;
	int DACval[2];
	for(;;)
  {
		for(i=0; i<4;i++)
		{
			setADCMux(i);
			osDelay(1);	
			adctemp = Get_Adc(ADC_CHANNEL_0);  
			fADCval[i] = adctemp * gctrlinfo.adcscale[i] + gctrlinfo.adcoffset[i];
		}
		IOin = getDI();
		
		
		//sem_memcpy((void*)&gsensor,(void*)fADCval, 6*4);
		
		osSemaphoreWait(gDataSemHandle, osWaitForever);
		gsensor.WaterPressBef = fADCval[0];
		gsensor.WaterPressAft = fADCval[1];
		gsensor.OilPress = fADCval[2];
		gsensor.OilTemp = fADCval[3];
		gsensor.OilPos = fADCval[4];
		gsensor.OilVel = fADCval[5];
		gsensor.InStat = IOin;
		IOout = gsensor.OutStat;
		DACval[0] = gsensor.DACVal1;
		DACval[1] = gsensor.DACVal2;
		osSemaphoreRelease(gDataSemHandle);
		setDO(IOout);
		DACout(DACval[0], DACval[1]);	  
		osDelay(100);	
	}
}


extern float adc1val;
void GUIMainTask(void const * argument)
{
	
	printf("GUIMain task begin\n");
	CreateRTCtrl();
	for(;;)
  {
		adc1val = gsensor.WaterPressBef;
		GUI_Delay(1000);
		//GUI_Exec();
		RTCtrl();
		/*
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);   
    osDelay(500);										
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET);   
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET); 
    osDelay(500); 
		*/
	}
}

extern osThreadId ETHCMDTaskHandle;
extern osThreadId RWSensorIOTaskHandle;
extern osThreadId GUIMainTaskHandle;
extern osThreadId TouchTaskHandle;
extern osThreadId UARTCMDTaskHandle;

unsigned long ETHstack;
unsigned long sensorstack;
unsigned long GUIstack;
unsigned long Touchstack;
unsigned long UARTstack;
	
void TouchTask(void const * argument)
{

	while(LWIP_init_OK == 0);
	printf("Touch task begin\n");
	
	//eMBInit(MB_RTU, 0x02, 0, 9600, MB_PAR_NONE);
	eMBTCPInit(502 );
	eMBEnable();
	
	for(;;)
  {
			GUI_TOUCH_Exec();	
		  osDelay(100);  
			ETHstack	= uxTaskGetStackHighWaterMark(ETHCMDTaskHandle);
		sensorstack	= uxTaskGetStackHighWaterMark(RWSensorIOTaskHandle);
		GUIstack	= uxTaskGetStackHighWaterMark(GUIMainTaskHandle);
		Touchstack	= uxTaskGetStackHighWaterMark(TouchTaskHandle);
		UARTstack	= uxTaskGetStackHighWaterMark(UARTCMDTaskHandle);
		eMBPoll();
		
	}
		
}

